<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>原生JS实现购物车结算功能代码</title>
    <link rel="stylesheet" href="../css/style.css" />
    <script src="../js/vue.js"></script>
    <script src="../js/axios.min.js"></script>
    <style>
        .goods span {
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2;
            overflow: hidden;
            text-overflow: ellipsis;
        }
    </style>
</head>

<body>
    <div id="app">
        <p class="one">{{count}}</p>
        <br>
        <div class="catbox">
            <table id="cartTable">
                <thead>
                    <tr>
                        <th><label>
                                <!-- 选中/未选中  checkAll = true/false    -->
                                <input class="check-all check" type="checkbox"
                                    v-model="checkAll" />&nbsp;&nbsp;全选</label></th>
                        <th>商品</th>
                        <th>单价</th>
                        <th>数量</th>
                        <th>小计</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    <tr v-for="carItem in carList" :key="carItem.goodsId">
                        <td class="checkbox"><input class="check-one check" type="checkbox"
                                v-model="carItem.isChecked" /></td>
                        <td class="goods">
                            <img :src="carItem.goodsImg" alt="" />
                            <span>{{carItem.goodsName}}</span>
                        </td>
                        <td class="price" ref="priceTd">{{carItem.goodsPrice}}</td>
                        <td class="count"><span class="reduce"
                                @click="carItem.buyNum = (carItem.buyNum > 1 ? carItem.buyNum -1 : carItem.buyNum)">{{carItem.buyNum>1?"-":""}}</span>
                            <input class="count-input" type="text" v-model.lazy.number="carItem.buyNum" />
                            <span class="add" @click="carItem.buyNum++">+</span>
                        </td>
                        <td class="subtotal">{{(carItem.goodsPrice*carItem.buyNum).toFixed(2)}}</td>
                        <td class="operation"><span class="delete" @click="deleteOneHanlder(carItem)">删除</span></td>
                    </tr>
                </tbody>
            </table>
            <div class="foot" id="foot">
                <a class="fl" id="deleteAll" href="javascript:;" @click="deleteAllHandler">删除</a>
                <div class="fr closing" onclick="getTotal();">结 算</div>
                <input type="hidden" id="cartTotalPrice" />
                <div class="fr total">合计：￥<span id="priceTotal">{{priceTotal}}</span></div>
                <div class="fr selected" id="selected">已选商品<span id="selectedTotal">{{selectTotal}}</span>件<span
                        class="arrow up">︽</span><span class="arrow down">︾</span></div>
                <div class="selected-view">
                    <div id="selectedViewList" class="clearfix">
                        <div><img src="../images/1.jpg"><span>取消选择</span></div>
                    </div>
                    <span class="arrow">◆<span>◆</span></span>
                </div>
            </div>
        </div>
    </div>
</body>
<script>

    // Vue特征
    // 1. 声明式渲染(Vue实例Vue初始化)
    // 2. 响应式(Vue实例数据更新)

    // 生命周期分为三个阶段: 初始化阶段  更新阶段  销毁阶段   8个钩子函数

    // 初始化阶段
    // beforeCreate
    // 第一个生命周期钩子函数,发生在Vue实例创建之后, 进行数据侦听(data)和事件/侦听器(watch)的配置之前同步调用,此时Vue实例选项(new Vue(options))配置之前

    // created
    // 在实例创建完成后被立即同步调用。在这一步中，实例已完成对选项的处理，意味着以下内容已被配置完毕：数据侦听、计算属性、方法、事件 / 侦听器的回调函数。然而，挂载阶段还没开始，且 $el property 目前尚不可用。

    // beforeMount
    // 在挂载开始之前被调用：相关的 render 函数首次被调用。 通过render()函数将模板便以为vDom (虚拟DOM), 此时还未渲染真实DOM


    // mounted
    // 实例被挂载后调用，这时 el 被新创建的 vm.$el 替换了。如果根实例挂载到了一个文档内的元素上，当 mounted 被调用时 vm.$el 也在文档内。
    // vDom  解析为真实DOM 渲染到挂载的元素中

    // beforeUpdate
    // updated

    // beforeDestroy
    // destroyed

    var vm = new Vue({
        el: "#app",
        data: {
            count: 0,
            carList: [],
        },
        methods: {
            getData() {
                axios.get("../data/shoppingCar.json").then(res => res.data).then(result => {
                    var { code, message, list } = result;
                    if (code == true) {
                        this.carList = list;
                    }
                })
            },
            deleteOneHanlder(item) {
                var index = this.carList.indexOf(item);
                this.carList.splice(index, 1);
            },
            deleteAllHandler() {
                //   删除所有选中商品  => 变相的说,留下的就是未选中的商品  => 查找未选中的商品,赋值给carList
                this.carList = this.carList.filter(v => v.isChecked == false);

            }
        },
        computed: {
            checkAll: {
                // 全选取值  (什么时候全部选中 => 每件商品的isChecked都为true)
                get() {
                    console.log("计算属性checkAll执行了");
                    var flag = this.carList.every(v => v.isChecked);
                    return this.carList.length > 0 ? flag : false;
                },
                set(bool) {
                    console.log("checkAll赋值");
                    // 所有单选的选中状态 依赖于全选的选中状态
                    this.carList.forEach(v => {
                        v.isChecked = bool;
                    })
                }
            },
            selectTotal() {
                return this.carList.reduce((prev, item) => item.isChecked ? prev + item.buyNum : prev, 0);
            },
            priceTotal() {
                return this.carList.reduce((prev, item) => item.isChecked ? prev + item.buyNum * item.goodsPrice : prev, 0).toFixed(2);
            },
            carListCopy: function () {
                return JSON.parse(JSON.stringify(this.carList));
            }
        },
        watch: {
            // 可以监听到数组carList上的数据变化,但是无法监听到carList中对象的数据的变化
            // carList: function (newVal, oldVal) {
            //     console.log("carList发生了改变");
            // },

            // 深度监听
            // a. 可以监听到数组carList上的数据变化
            // b. 也可以监听到carList中对象的数据的变化 (但是无法监听到哪个属性发生了变化)
            // carList: {
            //     handler: function (newVal, oldVal) {
            //         console.log("carList发生了改变", newVal, oldVal);
            //     },
            //     deep: true,
            // }


            carListCopy: function (newVal, oldVal) {
                // console.log("carList发生了改变", newVal, oldVal); //     []
                // oldVal初始是空数组  页面初始渲染后请求数据  => [{},{},{},{},{}]
                if (oldVal.length > 0) {
                    console.log("第一件商品发生了改变", newVal[0].buyNum, oldVal[0].buyNum);

                    newVal.forEach((v, i) => {

                        // 如果buyNum小于1 或 不是整数
                        if (v.buyNum < 1 || v.buyNum % 1 != 0) {

                            // 如果buyNum出错 => carList中的数据也出错 => 还原carList中的数据
                            this.carList[i].buyNum = oldVal[i].buyNum;
                        }

                    })

                }
            }
        },
        beforeCreate: function () {
            console.log("1. beforeCreate 实例", this);
            console.log("1. beforeCreate 数据", this.$data, this.count, this.carList);
            console.log("1. beforeCreate 方法", this.getData);
            console.log("1. beforeCreate 计算属性", this.checkAll);
            console.log("1. beforeCreate $el", this.$el);
        },
        created: function () {
            // new Vue(options) 选项已经配置完毕
            console.log("2. created 实例", this);
            console.log("2. created 数据", this.$data, this.count, this.carList);
            console.log("2. created 方法", this.getData);
            console.log("2. created 计算属性", this.checkAll);
            console.log("2. created $el", this.$el);
        },
        beforeMount: function () {
            console.log("3.beforeMount 实例", this);
            console.log("3.beforeMount 数据", this.$data, this.count, this.carList);
            console.log("3.beforeMount 方法", this.getData);
            console.log("3.beforeMount 计算属性", this.checkAll);
            var one = document.getElementsByClassName("one")[0];
            console.log("3.beforeMount 模板", one);
            console.log("3.beforeMount $el", this.$el);
        },
        mounted() {
            console.log("4.mounted 实例", this);
            console.log("4.mounted 数据", this.$data, this.count, this.carList);
            console.log("4.mounted 方法", this.getData);
            console.log("4.mounted 计算属性", this.checkAll);
            var one = document.getElementsByClassName("one")[0];
            console.log("4.mounted 模板", one);
            console.log("4.mounted $el", this.$el);
            // this.getData();
        },
    })

</script>

</html>